#ifndef __ENDIAN_HPP__
#define __ENDIAN_HPP__

#include "Debug.hpp"

#include <cstdint>

namespace Endian {

enum Endianness
{
	LITTLE_ENDIAN = 0x494B4952,
	BIG_ENDIAN = 0x52494B49
};

static union ByteOrder
{
	uint32_t i;
	char c[sizeof(uint32_t)];
	Endianness hostEndianness;
			
	ByteOrder() : i(BIG_ENDIAN)
	{
		hostEndianness = c[0] == 0x52 ? BIG_ENDIAN : LITTLE_ENDIAN;
	}
} byteOrder;

template<typename T, Endianness useEndian = LITTLE_ENDIAN>
class CEndian
{
private:
	T swapped;

	static T Swap(const T& data)
	{
		if(byteOrder.hostEndianness == useEndian)
			return data;
		else
		{
			T ret;

			char* dst = reinterpret_cast<char*>(&ret);
			const char* src = reinterpret_cast<const char*>(&data + 1);
 
			for(size_t i = 0; i < sizeof(T); i++)
				*dst++ = *--src;

			return ret;
		}
	}

public:
	CEndian() { }
	CEndian(const T& t) : swapped(Swap(t)) { }
	operator T() const { return Swap(swapped); }
};

} // namespace Endian

#endif